package com.sz.biz.logistics.ord.service.impl;

import com.google.common.collect.Lists;
import com.sz.biz.common.constants.CommCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.logistics.ord.entity.BizOperationLog;
import com.sz.biz.logistics.core.entity.Product;
import com.sz.biz.trade.ord.entity.TrdOrderStatus;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.biz.logistics.ord.service.BizOperationLogService;
import com.sz.biz.logistics.core.service.ProductService;
import com.sz.biz.trade.ord.dto.TrdOrderFileRelDto;
import com.sz.biz.logistics.ord.dto.*;
import com.sz.biz.logistics.ord.entity.*;
import com.sz.common.base.constants.AppDomain;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.base.utils.JsonUtils;
import com.sz.biz.logistics.ord.service.OrdOrderStatusCodeService;
import com.sz.biz.logistics.ord.service.OrdOrderTrackingService;
import com.sz.biz.logistics.ord.enums.OrdOperationLogEnum;
import com.sz.common.base.utils.ObjectUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.service.SysUserSupport;
import com.sz.common.core.system.service.UserModel;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Package: com.sz.biz.logistics.ord.service.impl<br>
 * Function: 操作日志service
 * Author: yanhong.xiao.<br>
 * Date: 2017-10-10 15:53:00.
 */
@Service("bizOperationLogService")
public class BizOperationLogServiceImpl extends AbstractService implements BizOperationLogService {

    private static final int ADDRESS_LEN = 13;
    @Autowired
    private ProductService productService;

    @Autowired
    private OrdOrderStatusCodeService orderStatusCodeService;


    @Autowired
    private OrdOrderTrackingService trackingService;

    @Autowired
    private CustomerUserService customerUserService;


    @Autowired
    private SysUserSupport sysUserSupport;


    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.ord.entity.BizOperationLogMapper";
    }


    /**
     * @param module    模块名称
     * @param subModule 子模块名称
     * @param logs      日志记录
     */
    @Override
    public void saveOperationLog(String module, String subModule, List<BizOperationLog> logs, Integer accountId, Integer domainId) {
        if (CollectionUtils.isNotEmpty(logs)) {
            logs.forEach(log -> {
                log.setModule(module);
                log.setSubModule(subModule);
                log.setAccountId(accountId);
                log.setOperSource(domainId);
            });
            // 保存到数据库
            dao.batchInsert(getSqlName("insertSelective"), logs);
        }
    }

    /**
     * 创建订单时，保存草稿或者直接提交的操作日志
     *
     * @param orderIds
     * @param accountId
     * @param domainId
     */
    @Async
    @Override
    public void saveOrdOperLogForDraftOrCommit(List<Integer> orderIds, Integer accountId, Integer domainId, OrdOperationLogEnum operationLogEnum) {
        List<BizOperationLog> logs = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(orderIds)) {
            orderIds.forEach(orderId -> {
                BizOperationLog log = new BizOperationLog();
                log.setRefNum(String.valueOf(orderId));
                log.setOperType(UserActions.ADD);
                log.setEventType(operationLogEnum.getCode());
                //组装数据
                OrdOperLogData logData = new OrdOperLogData();
                List<String> recordTxtList = Lists.newArrayList();
                recordTxtList.add(operationLogEnum.getName());
                logData.setRecordTxtList(recordTxtList);
                log.setData(JsonUtils.toJSONString(logData));
                //状态为草稿状态
                if (operationLogEnum == OrdOperationLogEnum.CREATE_DRAFT) {
                    log.setExtra(OrderStatus.DRAFT.getCode());
                }else{
                    log.setExtra(OrderStatus.COMMITED.getCode());
                }
                logs.add(log);
            });
            saveOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, logs, accountId, domainId);
        }
    }

    /**
     * 提交订单
     * 1.创建订单时，直接提交。  add  不在此方法中
     * 2 草稿编辑到提交。 update
     * 3 草稿列表直接提交，不在此方法中
     *
     * @param orderIds
     * @param oldOrderDtoMap
     * @param newOrderDtoMap
     * @param operType
     * @param accountId
     * @param domainId
     */
    @Override
    @Async
    public void saveOrdOperLogForCommit(List<Integer> orderIds, Map<Integer, OrdOrderDto> oldOrderDtoMap, Map<Integer, OrdOrderDto> newOrderDtoMap, String operType, Integer accountId, Integer domainId) {
        List<BizOperationLog> logs = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(orderIds) && orderIds.size() == oldOrderDtoMap.size() && orderIds.size() == newOrderDtoMap.size()) {
            orderIds.forEach(orderId -> {
                BizOperationLog log = new BizOperationLog();
                log.setRefNum(String.valueOf(orderId));
                log.setOperType(operType);
                log.setEventType(OrdOperationLogEnum.SUBMIT_ORDER.getCode());
                //组装data
                OrdOperLogData submitData = new OrdOperLogData();
                log.setExtra(OrderStatus.COMMITED.getCode());
                //如果是订单修改操作让状态变为已经提交，先判断是否有订单信息的修改
                if (operType.equals(UserActions.UPDATE)) {
                    //需要比较两者之间的差异
                    OrdOrderDto oldOrderDto = oldOrderDtoMap.get(orderId);
                    OrdOrderDto newOrderDto = newOrderDtoMap.get(orderId);
                    List<OrdOperLogUpData> updateData = compareOrderDto(oldOrderDto, newOrderDto);
                    submitData.setUpDataList(updateData);
                    if (oldOrderDto.getOrderStatus() == OrderStatus.DRAFT) {
                        //从草稿到提交
                        log.setExtra(OrderStatus.DRAFT.getCode() + "->" + OrderStatus.COMMITED.getCode());
                    }
                }
                List<String> submitRecordList = Lists.newArrayList();
                submitRecordList.add(OrdOperationLogEnum.SUBMIT_ORDER.getName());
                submitData.setRecordTxtList(submitRecordList);
                log.setData(JsonUtils.toJSONString(submitData));
                logs.add(log);
            });
            saveOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, logs, accountId, domainId);
        }

    }

    /**
     * 订单信息的修改
     *
     * @param orderIds
     * @param oldOrderDtoMap
     * @param newOrderDtoMap
     * @param operType
     * @param accountId
     * @param domainId
     */
    @Override
    @Async
    public void saveOrdOperLogForUpdate(List<Integer> orderIds, Map<Integer, OrdOrderDto> oldOrderDtoMap, Map<Integer, OrdOrderDto> newOrderDtoMap, String operType, Integer accountId, Integer domainId) {
        List<BizOperationLog> logs = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(orderIds) && orderIds.size() == oldOrderDtoMap.size() && orderIds.size() == newOrderDtoMap.size()) {

            orderIds.forEach(orderId -> {
                BizOperationLog log = new BizOperationLog();
                log.setRefNum(String.valueOf(orderId));
                log.setOperType(operType);
                log.setEventType(OrdOperationLogEnum.ORDER_INFO_UPDATE.getCode());

                //组装data
                OrdOperLogData infoUpdateLog = new OrdOperLogData();
                //需要比较两者之间的差异
                OrdOrderDto oldOrderDto = oldOrderDtoMap.get(orderId);
                OrdOrderDto newOrderDto = newOrderDtoMap.get(orderId);
                List<OrdOperLogUpData> updateData = compareOrderDto(oldOrderDto, newOrderDto);
                infoUpdateLog.setUpDataList(updateData);
                if (CollectionUtils.isEmpty(updateData)) {
                    //未做任何内容修改
                    List<String> recordList = Lists.newArrayList();
                    recordList.add("未做任何内容修改");
                    infoUpdateLog.setRecordTxtList(recordList);
                }
                log.setData(JsonUtils.toJSONString(infoUpdateLog));
                log.setExtra(oldOrderDto.getOrderStatus().getCode());
                if (newOrderDto.getOrderStatus().compareTo(oldOrderDto.getOrderStatus()) > 0) {
                    log.setExtra(log.getExtra() + "->" + newOrderDto.getOrderStatus().getCode());
                }
                logs.add(log);
            });

            saveOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, logs, accountId, domainId);
        }

    }

    /**
     * 订单批量受理或者批量提交
     *
     * @param orderIds
     * @param operType
     * @param accountId
     * @param domainId
     * @return
     */

    @Async
    @Override
    public void saveOrdOperLogForBatchAcceptOrSubmit(List<Integer> orderIds, String operType, Integer accountId, Integer domainId, OrdOperationLogEnum operationLogEnum) {
        List<BizOperationLog> logs = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(orderIds)) {
            orderIds.forEach(orderId -> {
                BizOperationLog log = new BizOperationLog();
                log.setRefNum(String.valueOf(orderId));
                log.setOperType(operType);
                switch (operationLogEnum) {
                    case SUBMIT_ORDER:
                        log.setEventType(OrdOperationLogEnum.SUBMIT_ORDER.getCode());
                        log.setExtra(OrderStatus.DRAFT.getCode() + "->" + OrderStatus.COMMITED.getCode());
                        OrdOperLogData logData = new OrdOperLogData();
                        List<String> submitRecordList = Lists.newArrayList();
                        submitRecordList.add(OrdOperationLogEnum.SUBMIT_ORDER.getName());
                        logData.setRecordTxtList(submitRecordList);
                        log.setData(JsonUtils.toJSONString(logData));
                        break;
                    case ACCEPT_ORDER:
                        log.setEventType(OrdOperationLogEnum.ACCEPT_ORDER.getCode());
                        log.setExtra(OrderStatus.COMMITED.getCode() + "->" + OrderStatus.ACCEPT.getCode());
                        OrdOperLogData acceptLogData = new OrdOperLogData();
                        List<String> acceptRecordList = Lists.newArrayList();
                        if (PrincipalUtils.getDomainId() == AppDomain.EDIDATA) {
                            acceptRecordList.add("系统自动受理订单");
                        } else {
                            acceptRecordList.add("手动受理订单");
                        }
                        acceptLogData.setRecordTxtList(acceptRecordList);
                        log.setData(JsonUtils.toJSONString(acceptLogData));
                        break;
                    default:
                        return;
                }
                logs.add(log);
            });
        }
        saveOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, logs, accountId, domainId);
    }

    /**
     * @param orderId
     * @param originalSubOrder
     * @param subOrder
     * @param originalOrder
     * @param order
     * @param operType
     * @param eventTypeEnum
     */
    @Async
    @Override
    public void saveOrdLogisInfoUpdateLog(Integer orderId, OrdSubOrder originalSubOrder, OrdSubOrder subOrder, OrdOrder originalOrder, OrdOrder order, String operType, OrdOperationLogEnum eventTypeEnum, OrdOrderTracking tracking, Integer accountId, Integer domainId) {
        //物流信息修改
        if (eventTypeEnum == OrdOperationLogEnum.LOGISTICS_INFO_UPDATE) {
            List<BizOperationLog> logs = Lists.newArrayList();
            BizOperationLog bizLog = new BizOperationLog();
            bizLog.setRefNum(String.valueOf(orderId));
            bizLog.setOperType(operType);
            bizLog.setEventType(eventTypeEnum.getCode());
            //extra
            bizLog.setExtra(originalOrder.getOrderStatus().getCode());
            if (null != order && null != order.getOrderStatus() && order.getOrderStatus().compareTo(originalOrder.getOrderStatus()) > 0) {
                bizLog.setExtra(bizLog.getExtra() + "->" + order.getOrderStatus().getCode());
            }

            OrdOperLogData logData = new OrdOperLogData();
            if(!ObjectUtils.isEmpty(tracking)) {
                OrdOrderStatusCode ordOrderStatusCode = orderStatusCodeService.getByCode(tracking.getCode());
                if (null != ordOrderStatusCode) {
                    String messageTemplate = ordOrderStatusCode.getMessageTemplate();
                    String trackContext = trackingService.getTrackingString(messageTemplate, tracking.getTrackMessage());
                    List<String> recordList = Lists.newArrayList();
                    recordList.add("子单" + originalSubOrder.getSubOrderNo() + "增加物流信息:" + trackContext);
                    logData.setRecordTxtList(recordList);
                }
            }
            List<OrdOperLogUpData> upDatas = Lists.newArrayList();
            if (null != order && order.getOrderStatus() == OrderStatus.RECEGOOD) {
                //已收货时，订单信息变化,在订单的计费重量，计费重量单位.
                bizLog.setExtra(originalOrder.getOrderStatus().getCode() + "->" + order.getOrderStatus().getCode());
                //计费重量
                OrdOperLogUpData orderParam = new OrdOperLogUpData();
                orderParam.setParamName("feeWeight");
                if (null == originalOrder.getSupWeight() && null != order.getSupWeight()) {
                    orderParam.setLaterValue(order.getSupWeight() + order.getSupWeightUnit());
                } else if (null != originalOrder.getSupWeight() && null == order.getSupWeight()) {
                    orderParam.setPreValue(originalOrder.getSupWeight() + originalOrder.getSupWeightUnit());
                } else if (null != originalOrder.getSupWeight() && null != order.getSupWeight()) {
                    if (!originalOrder.getSupWeight().equals(order.getSupWeight()) || !originalOrder.getSupWeightUnit().equals(order.getSupWeightUnit())) {
                        orderParam.setPreValue(originalOrder.getSupWeight() + originalOrder.getSupWeightUnit());
                        orderParam.setLaterValue(order.getSupWeight() + order.getSupWeightUnit());
                    }
                }
                if (null != orderParam.getPreValue() || null != orderParam.getLaterValue()) {
                    upDatas.add(orderParam);
                }
            }
            if (null != subOrder && subOrder.getOrderStatus() == OrderStatus.RECEGOOD) {
                //已收货时,子单信息变化,在子单的货物件数，子单长，子单宽，子单高，子单重量，子单长宽高，子单的长宽高单位，子单重量单位
                if (!originalSubOrder.equals(subOrder)) {
                    OrdOperLogUpData subOrderParam = new OrdOperLogUpData();
                    subOrderParam.setParamName("subOrder");
                    subOrderParam.setPreValue(getSubOrderInfo(originalSubOrder));
                    subOrderParam.setLaterValue(getSubOrderInfo(subOrder));
                    upDatas.add(subOrderParam);
                }
            }
            logData.setUpDataList(upDatas);
            bizLog.setData(JsonUtils.toJSONString(logData));
            logs.add(bizLog);
            saveOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, logs, accountId, domainId);
        }

    }

    /**
     * 批量增加物流信息的操作日志
     *
     * @param subOrderList
     * @param orderStatusMap
     */

    @Async
    @Override
    public void batchSaveLogisInfoForUpdateLog(List<OrdOrder> orderList, List<OrdSubOrder> subOrderList, List<OrdOrder> orderListForSub, String trackMessage, Map<String, OrderStatus> orderStatusMap, Integer accountId, Integer domainId) {
        List<BizOperationLog> logs = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(orderList)) {
            if (CollectionUtils.isNotEmpty(orderList)) {
                for (OrdOrder order :
                        orderList) {
                    BizOperationLog bizLog = new BizOperationLog();
                    bizLog.setRefNum(String.valueOf(order.getId()));
                    bizLog.setOperType(UserActions.ADD);
                    bizLog.setEventType(OrdOperationLogEnum.LOGISTICS_INFO_UPDATE.getCode());
                    bizLog.setExtra(order.getOrderStatus().getCode());
                    if (null != orderStatusMap && orderStatusMap.containsKey(order.getOrderNo())) {
                        OrderStatus newStatus = orderStatusMap.get(order.getOrderNo());
                        if (newStatus.compareTo(order.getOrderStatus()) > 0) {
                            bizLog.setExtra(bizLog.getExtra() + "->" + newStatus.getCode());
                        }
                    }

                    OrdOperLogData logData = new OrdOperLogData();
                    List<String> recordList = Lists.newArrayList();
                    recordList.add("给所有子单增加物流信息:" + trackMessage);
                    logData.setRecordTxtList(recordList);
                    bizLog.setData(JsonUtils.toJSONString(logData));
                    logs.add(bizLog);
                }
            }
        }
        //子单不为空
        if (CollectionUtils.isNotEmpty(subOrderList)) {
            Map<String, OrdOrder> orderMapForSub = new HashedMap();
            if (CollectionUtils.isNotEmpty(orderListForSub)) {
                orderListForSub.forEach(ordOrder -> {
                    orderMapForSub.put(ordOrder.getOrderNo(), ordOrder);
                });
            }
            Map<String, OrdOrder> subToOrderMap = new HashedMap();
            subOrderList.forEach(ordSubOrder -> {
                subToOrderMap.put(ordSubOrder.getSubOrderNo(), orderMapForSub.get(ordSubOrder.getOrderNo()));
            });
            if (CollectionUtils.isNotEmpty(orderListForSub)) {
                for (OrdSubOrder subOrder :
                        subOrderList) {
                    if (subToOrderMap.containsKey(subOrder.getSubOrderNo())) {
                        OrdOrder subToOrder = subToOrderMap.get(subOrder.getSubOrderNo());
                        if (null != subToOrder) {
                            BizOperationLog bizLog = new BizOperationLog();
                            bizLog.setRefNum(String.valueOf(subToOrder.getId()));
                            bizLog.setOperType(UserActions.ADD);
                            bizLog.setEventType(OrdOperationLogEnum.LOGISTICS_INFO_UPDATE.getCode());
                            OrdOperLogData logData = new OrdOperLogData();
                            List<String> recordList = Lists.newArrayList();
                            recordList.add("子单号:" + subOrder.getSubOrderNo() + "增加物流信息:" + trackMessage);
                            logData.setRecordTxtList(recordList);
                            bizLog.setData(JsonUtils.toJSONString(logData));
                            bizLog.setExtra(subToOrder.getOrderStatus().getCode());
                            if (null != orderStatusMap && orderStatusMap.containsKey(subToOrder.getOrderNo())) {
                                OrderStatus newStatus = orderStatusMap.get(subToOrder.getOrderNo());
                                if (newStatus.compareTo(subToOrder.getOrderStatus()) > 0) {
                                    bizLog.setExtra(bizLog.getExtra() + "->" + newStatus.getCode());
                                }
                            }
                            logs.add(bizLog);
                        }
                    }
                }
            }
        }
        saveOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, logs, accountId, domainId);
    }


    /**
     * 比对订单的差异
     * 1. 客户
     * 2. 客户单号
     * 3. 产品
     * 4. 服务---- (主服务和必选服务都是默认选择的， 对比可选服务即可)
     * 5. 货物类型
     * 6. 货物件数
     * 7. 货物总重
     * 8. 始发地址及联系人信息
     * 9. 目的地址及联系人信息
     * 10.物品明细
     * 11. 附件信息
     * 12. 客户留言
     *
     * @param oldOrderDto
     * @param newOrderDto
     * @return
     */
    @Override
    public List<OrdOperLogUpData> compareOrderDto(OrdOrderDto oldOrderDto, OrdOrderDto newOrderDto) {
        List<OrdOperLogUpData> resultData = Lists.newArrayList();
        //比对客户
        if (oldOrderDto.getCusUserId().intValue() != newOrderDto.getCusUserId().intValue()) {
            OrdOperLogUpData customerNameParam = new OrdOperLogUpData();
            customerNameParam.setParamName("customerName");
            CusUser oldCusUser = customerUserService.findById(oldOrderDto.getCusUserId());
            if (null != oldCusUser) {
                customerNameParam.setPreValue(oldCusUser.getFullName() + "(" + oldCusUser.getUserName() + ")");
            }
            CusUser cusUser = customerUserService.findById(newOrderDto.getCusUserId());
            if (null != cusUser) {
                customerNameParam.setLaterValue(cusUser.getFullName() + "(" + cusUser.getUserName() + ")");
            }
            resultData.add(customerNameParam);
        }
        //比对客户单号
        if (!oldOrderDto.getExternalNo().equals(newOrderDto.getExternalNo())) {
            OrdOperLogUpData externalNoParam = new OrdOperLogUpData();
            externalNoParam.setParamName("externalNo");
            externalNoParam.setPreValue(oldOrderDto.getExternalNo());
            externalNoParam.setLaterValue(newOrderDto.getExternalNo());
            resultData.add(externalNoParam);
        }
        //比对产品
        if (!oldOrderDto.getProductUid().equals(newOrderDto.getProductUid())) {
            OrdOperLogUpData productNameParam = new OrdOperLogUpData();
            productNameParam.setParamName("productName");
            Product oldProduct = productService.findByUid(oldOrderDto.getProductUid());
            Product newProduct = productService.findByUid(newOrderDto.getProductUid());
            if (null != oldProduct) {
                productNameParam.setPreValue(oldProduct.getName() + "(" + oldProduct.getCode() + ")");
            }
            if (null != newProduct) {
                productNameParam.setLaterValue(newProduct.getName() + "(" + newProduct.getCode() + ")");
            }
            resultData.add(productNameParam);
        }
        //比对可选服务
        List<OrdOrderAdditionalDto> oldAdditionalDtos = oldOrderDto.getOrderAdditionalDtos();
        List<OrdOrderAdditionalDto> newAdditionalDtos = newOrderDto.getOrderAdditionalDtos();
        List<String> oldAdditionalTypeCodeNames = Lists.newArrayList(); 
        StringBuilder oldOptionalTypeCodeName = new StringBuilder(); 
        List<String> newOptionalTypeCodeNames = Lists.newArrayList(); 
        StringBuilder newOptionalTypeCodeName = new StringBuilder();
        if (CollectionUtils.isNotEmpty(oldAdditionalDtos)) {
            oldAdditionalDtos.forEach(d -> {
                oldAdditionalTypeCodeNames.add(d.getServiceTypeName());
                oldOptionalTypeCodeName.append(d.getServiceTypeName() + ",");
            });
        }
        if (CollectionUtils.isNotEmpty(newAdditionalDtos)) {
            newAdditionalDtos.forEach(d -> {
                newOptionalTypeCodeNames.add(d.getServiceTypeName());
                newOptionalTypeCodeName.append(d.getServiceTypeName() + ",");
            });
        }
        //看有没有不同的可选服务
        boolean addtionalFlag = EntityUtils.compareListT(oldAdditionalTypeCodeNames, newOptionalTypeCodeNames);
        if (!addtionalFlag) {
            //可选服务有差异,需要记录.
            OrdOperLogUpData additionalServiceParam = new OrdOperLogUpData();
            //附加服务
            additionalServiceParam.setParamName("orderAdditionalDtos");
            additionalServiceParam.setPreValue(oldOptionalTypeCodeName.toString());
            additionalServiceParam.setLaterValue(newOptionalTypeCodeName.toString());
            resultData.add(additionalServiceParam);
        }
        //比对货物类型
        if (!oldOrderDto.getCargoTypeName().equals(newOrderDto.getCargoTypeName())) {
            OrdOperLogUpData cargoTypeParam = new OrdOperLogUpData();
            cargoTypeParam.setParamName("cargoTypeName");
            cargoTypeParam.setPreValue(oldOrderDto.getCargoTypeName());
            cargoTypeParam.setLaterValue(newOrderDto.getCargoTypeName());
            resultData.add(cargoTypeParam);
        }
        //比对货物件数
        if (oldOrderDto.getPackageNum().intValue() != newOrderDto.getPackageNum().intValue()) {
            OrdOperLogUpData packageNumParam = new OrdOperLogUpData();
            packageNumParam.setParamName("packageNum");
            packageNumParam.setPreValue(String.valueOf(oldOrderDto.getPackageNum()));
            packageNumParam.setLaterValue(String.valueOf(newOrderDto.getPackageNum()));
            resultData.add(packageNumParam);
        }
        //比对货物总重量
        if (oldOrderDto.getCusWeight().compareTo(newOrderDto.getCusWeight()) != 0 || !oldOrderDto.getCusWeightUnit().equals(newOrderDto.getCusWeightUnit())) {
            OrdOperLogUpData cargoParam = new OrdOperLogUpData();
            cargoParam.setParamName("cargoTotalWeight");
            cargoParam.setPreValue(oldOrderDto.getCusWeight().stripTrailingZeros() + " " + oldOrderDto.getCusWeightUnit());
            cargoParam.setLaterValue(newOrderDto.getCusWeight() + " " + newOrderDto.getCusWeightUnit());
            resultData.add(cargoParam);
        }
        // 0联系人名称|1固定电话|2联系人电话|3国家|4省份|5城市|6区域|7街道|8运输类型|9港口或者机场名字|10详细地址|11邮编

        // 王海鹏哥哥|固定电话|13720053852|美国||JUNEAU|||全球速递|机场/陆运空/海运港口|我是一个家
        /**
         * 陆运  国内: 联系人名称  国家 省份 城市 区域 街道  详细地址  邮编
         * 联系电话 固定电话
         *
         * 国外:
         * 联系人名称 国家  城市 详细地址   邮编
         * 联系电话 固定电话
         */
        /**
         *  空运 获取联系人名称，国家，机场，详细地址，邮编
         联系电话，固定电话
         */
        /**
         * 海运
         * 联系人名称， 国家，港口，详细地址，邮编
         *  联系电话，固定电话
         */
        //比对始发地址及联系人信息
        if (!oldOrderDto.getFromDetail().equals(newOrderDto.getFromDetail())) {
            OrdOperLogUpData fromAddressParam = new OrdOperLogUpData();
            fromAddressParam.setParamName("fromAddress");
            String preFrom = getAddress(oldOrderDto.getFromAddress().getTransportType(), oldOrderDto.getFromDetail());
            fromAddressParam.setPreValue(preFrom);
            String laterFrom = getAddress(newOrderDto.getFromAddress().getTransportType(), newOrderDto.getFromDetail());
            fromAddressParam.setLaterValue(laterFrom);
            resultData.add(fromAddressParam);
        }
        //比对目的地址及联系人信息
        if (!oldOrderDto.getToDetail().equals(newOrderDto.getToDetail())) {
            OrdOperLogUpData toAddressPraram = new OrdOperLogUpData();
            toAddressPraram.setParamName("toAddress");
            String preTo = getAddress(oldOrderDto.getToAddress().getTransportType(), oldOrderDto.getToDetail());
            toAddressPraram.setPreValue(preTo);
            String laterTo = getAddress(newOrderDto.getToAddress().getTransportType(), newOrderDto.getToDetail());
            toAddressPraram.setLaterValue(laterTo);
            resultData.add(toAddressPraram);
        }
        //比对提货地址以及联系人信息
        OrdOperLogUpData fetchAddressPraram = new OrdOperLogUpData();
        fetchAddressPraram.setParamName("fetchAddress");
        String preFetch = null;
        String laterFetch = null;
        if (null == oldOrderDto.getFetchDetail() && null != newOrderDto.getFetchDetail()) {
            laterFetch = getAddress(newOrderDto.getFetchAddress().getTransportType(), newOrderDto.getFetchDetail());
        } else if (null != oldOrderDto.getFetchDetail() && null == newOrderDto.getFetchDetail()) {
            preFetch = getAddress(oldOrderDto.getFetchAddress().getTransportType(), oldOrderDto.getFetchDetail());
        } else if (null != oldOrderDto.getFetchDetail() && null != newOrderDto.getFetchDetail()) {
            if (!oldOrderDto.getFetchDetail().equals(newOrderDto.getFetchDetail())) {
                preFetch = getAddress(oldOrderDto.getFetchAddress().getTransportType(), oldOrderDto.getFetchDetail());
                laterFetch = getAddress(newOrderDto.getFetchAddress().getTransportType(), newOrderDto.getFetchDetail());
            }
        }
        if (StringUtils.isNotBlank(preFetch)) {
            fetchAddressPraram.setPreValue(preFetch);
        }
        if (StringUtils.isNotBlank(laterFetch)) {
            fetchAddressPraram.setLaterValue(laterFetch);
        }
        if (null != preFetch || null != laterFetch) {
            resultData.add(fetchAddressPraram);
        }
        //比对物品明细
        boolean flag = EntityUtils.compareListT(oldOrderDto.getOrderCargoDtos(), newOrderDto.getOrderCargoDtos());
        if (!flag) {
            //有差异
            String preCargoDetail = getOrderCargos(oldOrderDto);
            String laterCargoDetail = getOrderCargos(newOrderDto);
            OrdOperLogUpData cargoDtoParams = new OrdOperLogUpData();
            cargoDtoParams.setParamName("orderCargoDtos");
            cargoDtoParams.setPreValue(preCargoDetail);
            cargoDtoParams.setLaterValue(laterCargoDetail);
            resultData.add(cargoDtoParams);
        }
        //比对客户留言
        OrdOperLogUpData customerNotePraram = null;
        if (StringUtils.isEmpty(oldOrderDto.getCustomerNote()) && StringUtils.isNoneEmpty(newOrderDto.getCustomerNote())) {
            customerNotePraram = new OrdOperLogUpData();
        } else if (StringUtils.isNotEmpty(oldOrderDto.getCustomerNote()) && StringUtils.isEmpty(newOrderDto.getCustomerNote())) {
            customerNotePraram = new OrdOperLogUpData();
        } else if (StringUtils.isNotEmpty(oldOrderDto.getCustomerNote()) && StringUtils.isNotEmpty(newOrderDto.getCustomerNote())) {
            if (!(oldOrderDto.getCustomerNote().equals(newOrderDto.getCustomerNote()))) {
                customerNotePraram = new OrdOperLogUpData();
            }
        }
        if (null != customerNotePraram) {
            customerNotePraram.setParamName("customerNote");
            customerNotePraram.setPreValue(oldOrderDto.getCustomerNote());
            customerNotePraram.setLaterValue(newOrderDto.getCustomerNote());
            resultData.add(customerNotePraram);
        }
        return resultData;
    }


    private String getAddress(int transportType, String detail) {
        //处理修改后的地址
        String[] details = detail.split("\\|", -1);
        String address = "";
        //正确地址是13位
        if (details.length >= ADDRESS_LEN) {
            if (transportType == CommCodes.TRANSPORT_LAND) {
                //后来是陆运
                address = details[0] + " " + details[3] + " " + details[4] + " " + details[5] + " " + details[6] + " " + details[7] + " " + details[10];
            } else {
                //空运和海运
                address = details[0] + " " + details[3] + " " + details[9] + " " + details[10];
            }
            address += " 邮编：" + details[11] + " 移动电话：" + details[2] + " 固定电话：" + details[1] + " 邮箱：" + details[12];
        }
        return address;
    }


    private String getOrderCargos(OrdOrderDto orderDto) {
        List<OrdOrderCargoDto> cargos = orderDto.getOrderCargoDtos();
        String cargoDetail = "";
        String declarePrice = productService.getProductCurrencyByUid(orderDto.getProductUid());
        if (CollectionUtils.isNotEmpty(cargos)) {
            for (int i = 0; i < cargos.size(); i++) {
                OrdOrderCargoDto cargoDto = cargos.get(i);
                cargoDetail += " 物品名称：" + cargoDto.getGoodsNameCn() + " 英文名称：" + cargoDto.getGoodsNameEn() + " HS编码：" + cargoDto.getHsCode() + " 数量：" + cargoDto.getGoodsNumber() + " 计量单位：" + cargoDto.getGoodsUnitName() + " 声明价值(" + declarePrice + "）：" + cargoDto.getGoodsPrice().stripTrailingZeros() + " 物品描述：" + cargoDto.getDescription() + "；";
            }
        }
        return cargoDetail;

    }


    /**
     * 获取某个订单的操作日志
     *
     * @param orderId
     * @return
     */
    @Override
    public List<OrdOperLogDto> getLogsByOrderId(Integer orderId, String sort, Boolean asc) {
        List<OrdOperLogDto> dtoList = Lists.newArrayList();
        Map<String, Object> paramMap = new HashedMap();
        paramMap.put("module", ModuleNames.ORD);
        paramMap.put("subModule", ModuleNames.ORD_ORDER);
        paramMap.put("refNum", String.valueOf(orderId));
        if (StringUtils.isEmpty(sort)) {
            sort = "operTime";
        }
        paramMap.put("sort", sort);
        if (asc) {
            paramMap.put("order", "asc");
        } else {
            paramMap.put("order", "desc");
        }
        paramMap.put("asc", asc);
        List<BizOperationLog> logList = dao.findForList(getSqlName("queryLogs"), paramMap, BizOperationLog.class);
        if (CollectionUtils.isNotEmpty(logList)) {
            List<Integer> cusAccountIds = Lists.newArrayList();
            List<Integer> operAccountIds = Lists.newArrayList();
            for (BizOperationLog log :
                    logList) {
                if (log.getOperSource().equals(AppDomain.CUSTOMER)) {
                    cusAccountIds.add(log.getAccountId());
                } else {
                    operAccountIds.add(log.getAccountId());
                }
            }
            Map<Integer, CusUser> cusUserMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(cusAccountIds)) {
                //客户平台来源不为空
                cusAccountIds = com.sz.common.base.utils.CollectionUtils.removeDuplication(cusAccountIds);
                //获取用户的信息
                List<CusUser> cusUsers = customerUserService.findByIds(cusAccountIds);
                if (CollectionUtils.isNotEmpty(cusUsers)) {
                    cusUsers.forEach(cusUser -> cusUserMap.put(cusUser.getId(), cusUser));
                }
            }
            Map<Integer, UserModel> operUserMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(operAccountIds)) {
                operAccountIds = com.sz.common.base.utils.CollectionUtils.removeDuplication(operAccountIds);
                List<UserModel> operUsers = sysUserSupport.getUsersById(operAccountIds);
                if (CollectionUtils.isNotEmpty(operUsers)) {
                    operUsers.forEach(operUser -> {
                        //和需求确定账户名和全名
                        operUserMap.put(operUser.getUserId(), operUser);
                    });
                }
            }
            for (BizOperationLog log :
                    logList) {
                OrdOperLogDto dto = new OrdOperLogDto();
                dto.setId(log.getId());
                dto.setOperTime(log.getOperTime());
                dto.setEventName(OrdOperationLogEnum.valueOfEnum(log.getEventType()).getName());
                Integer operSource = log.getOperSource();
                String operSourceName = "";
                if (operSource == AppDomain.CUSTOMER) {
                    operSourceName = AppDomain.CUSTOMER_NAME;
                } else if (operSource == AppDomain.OPERATION) {
                    operSourceName = AppDomain.OPERATION_NAME;
                } else if (operSource == AppDomain.EDIDATA) {
                    operSourceName = AppDomain.EDIDATA_NAME;
                }
                if (log.getOperSource() == AppDomain.CUSTOMER) {
                    CusUser u = cusUserMap.get(log.getAccountId());
                    if (null != u) {
                        if (StringUtils.isNotEmpty(u.getFullName())) {
                            //名称
                            dto.setOperUserName(u.getFullName());
                        }
                        if (StringUtils.isNotEmpty(u.getUserName())) {
                            //账号
                            dto.setOperUserNum(u.getUserName());
                        }
                    }
                } else {
                    UserModel um = operUserMap.get(log.getAccountId());
                    if (null != um) {
                        if (StringUtils.isNotEmpty(um.getFullName())) {
                            dto.setOperUserName(um.getFullName());
                        }
                        if (StringUtils.isNotEmpty(um.getAccountName())) {
                            dto.setOperUserNum(um.getAccountName());
                        }
                    }
                }
                dto.setOperSource(operSourceName);
                if (StringUtils.isNotBlank(log.getExtra())) {
                    String[] orderStatusChanges = log.getExtra().split("->");
                    if (orderStatusChanges.length == 1) {
                        dto.setOrderStatusChange(OrderStatus.valueOfEnum(orderStatusChanges[0]).getName());
                    }
                    if (orderStatusChanges.length == 2) {
                        dto.setOrderStatusChange(OrderStatus.valueOfEnum(orderStatusChanges[0]).getName() + "->" + OrderStatus.valueOfEnum(orderStatusChanges[1]).getName());
                    }
                }
                dtoList.add(dto);
            }
        }
        return dtoList;
    }

    @Override
    public OrdOperLogData getById(Integer logId) {
        OrdOperLogData logData = null;
        BizOperationLog log = (BizOperationLog) dao.findForObject(getSqlName("selectByPrimaryKey"), logId);
        if (null != log) {
            logData = JsonUtils.toObject(log.getData(), OrdOperLogData.class);
        }
        return logData;
    }


    @Override
    @Async
    public void saveOrderFileUpdateLog(Integer orderId, OrderStatus orderStatus, String operType, OrdOrderFileDto fileDto, Integer accountId, Integer domainId) {
        if (null != fileDto) {
            BizOperationLog bizLog = new BizOperationLog();
            bizLog.setRefNum(String.valueOf(orderId));
            bizLog.setOperType(operType);
            bizLog.setEventType(OrdOperationLogEnum.ORDER_ATTACH_UPDATE.getCode());
            bizLog.setExtra(orderStatus.getCode());
            OrdOperLogData logData = new OrdOperLogData();
            List<String> recordList = Lists.newArrayList();
            String recordTxt;
            String fileTypeName = fileDto.getFileTypeName();
            if (operType.equals(UserActions.ADD)) {
                recordTxt = "增加附件:" + "  名称:" + fileDto.getFileName() + " 类型:" + fileTypeName + " 描述:" + fileDto.getDesciption();
            } else {
                //删除
                recordTxt = "删除附件:" + "  名称:" + fileDto.getFileName() + " 类型:" + fileTypeName + " 描述:" + fileDto.getDesciption();
            }
            recordList.add(recordTxt);
            logData.setRecordTxtList(recordList);
            bizLog.setData(JsonUtils.toJSONString(logData));
            List<BizOperationLog> logs = Lists.newArrayList();
            logs.add(bizLog);
            saveOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, logs, accountId, domainId);
        }
    }
    @Override
    @Async
    public void saveOrderFileUpdateLog(Integer trdOrderId, TrdOrderStatus trdOrderStatus, String operType, TrdOrderFileRelDto trdOrderFileRelDto, Integer accountId, Integer domainId) {
        if (null != trdOrderFileRelDto) {
            BizOperationLog bizLog = new BizOperationLog();
            bizLog.setRefNum(String.valueOf(trdOrderId));
            bizLog.setOperType(operType);
            bizLog.setEventType(OrdOperationLogEnum.ORDER_ATTACH_UPDATE.getCode());
            bizLog.setExtra(trdOrderStatus.getCode());
            OrdOperLogData logData = new OrdOperLogData();
            List<String> recordList = Lists.newArrayList();
            String recordTxt;
            if (operType.equals(UserActions.ADD)) {
                recordTxt = "增加附件:" + "  名称:" + trdOrderFileRelDto.getName() + " 描述:" + trdOrderFileRelDto.getRemark();
            } else {
                //删除
                recordTxt = "删除附件:" + "  名称:" + trdOrderFileRelDto.getName() +  " 描述:" + trdOrderFileRelDto.getRemark();
            }
            recordList.add(recordTxt);
            logData.setRecordTxtList(recordList);
            bizLog.setData(JsonUtils.toJSONString(logData));
            List<BizOperationLog> logs = Lists.newArrayList();
            logs.add(bizLog);
            saveOperationLog(ModuleNames.TRD, ModuleNames.TRD_ORDER_FILE, logs, accountId, domainId);
        }
    }


    private String getSubOrderInfo(OrdSubOrder subOrder) {
        StringBuilder subOrderValue = new StringBuilder("");
        subOrderValue.append("子单号:" + subOrder.getSubOrderNo());
        if (null != subOrder.getCargoNumber()) {
            subOrderValue.append("货物件数:" + subOrder.getCargoNumber());
        }
        if (null != subOrder.getLength()) {
            subOrderValue.append("长:" + subOrder.getLength());
        }
        if (null != subOrder.getWidth()) {
            subOrderValue.append("宽:" + subOrder.getWidth());
        }
        if (null != subOrder.getHeight()) {
            subOrderValue.append("高:" + subOrder.getHeight());
        }
        if (null != subOrder.getLwhUnit()) {
            subOrderValue.append("长宽高单位:" + subOrder.getLwhUnit());
        }
        if (null != subOrder.getWeight()) {
            subOrderValue.append("重量:" + subOrder.getWeight());
        }
        if (null != subOrder.getWeightUnit()) {
            subOrderValue.append("重量单位:" + subOrder.getWeightUnit());
        }
        return subOrderValue.toString();
    }


}
